package com.nulldev.util.io.extensions.nstream;

import java.io.Closeable;
import java.io.IOException;

import com.nulldev.util.data.longNumbers.lNumber;

public interface nStream extends Closeable {

	/* CORE */

	/**
	 * Is this nStream readable?
	 * 
	 * @returns value
	 */
	public boolean readable();

	/**
	 * Can this nStream be written to?
	 * 
	 * @returns value
	 */
	public boolean writeable();

	/**
	 * Attempts to catch up with I/O. <br>
	 * WARNING: This may freeze the current thread. <br>
	 * Also like: flush()
	 */
	public void sync() throws IOException;

	@Override
	/**
	 * Closes the current stream. <br>
	 * 
	 * @throws IOException
	 */
	public void close() throws IOException;

	/* READ */

	/**
	 * Reads the next X bytes.
	 * 
	 * @param bytes [Bytes to read]
	 * @throws IOException if this stream cannot be read from or is past EOF.
	 * @returns bytes <br>
	 *          If an EOF is hit, the byte array will be smaller than the original
	 *          size.
	 */
	public byte[] next(final int bytes) throws IOException;

	/**
	 * Reads the next byte.
	 * 
	 * @returns byte as an integer.
	 * @throws IOException if this stream cannot be read from or is past EOF.
	 */
	public int next() throws IOException;

	/**
	 * Reads byte X.
	 * 
	 * @param position
	 * @returns - The byte as an integer (-255,255) <br>
	 *          - The value '-256' if out of bounds.
	 * @throws IOException if this feature is unsupported
	 */
	public int at(final int position) throws IOException;

	/* EXTENDED_READ */

	/**
	 * Returns the current position.
	 * 
	 * @returns clamped integer
	 */
	public int positionLegacy();

	/**
	 * Returns the current position.
	 * 
	 * @returns Current Position
	 */
	public lNumber position();

	/**
	 * Resets the position count of the stream.
	 * 
	 * @throws UnsupportedOperationException If this stream cannot be reversed.
	 */
	public void reset() throws IOException, UnsupportedOperationException;

	public default lNumber available() throws UnsupportedOperationException {
		throw new UnsupportedOperationException("available is not supported!");
	}

	/* WRITE */

	/**
	 * Writes a byte into the stream.
	 * 
	 * @throws IOException <br>
	 *                     - If _byte is null. <br>
	 *                     - This stream cannot be written to.
	 */
	public void write(final int _byte) throws IOException;

	/**
	 * Writes a byte array into the stream.
	 * 
	 * @throws IOException <br>
	 *                     - If data is null or data's length is 0. <br>
	 *                     - This stream cannot be written to.
	 */
	public void write(final byte[] data) throws IOException;

}
